package cn.iocoder.yudao.module.infrastructure.wechat.service;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
import cn.binarywang.wx.miniapp.config.impl.WxMaRedisBetterConfigImpl;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.util.cache.CacheUtils;
import cn.iocoder.yudao.module.api.infrastructure.social.enums.SocialTypeEnum;
import cn.iocoder.yudao.module.infrastructure.social.dal.dataobject.SocialClientDO;
import cn.iocoder.yudao.module.infrastructure.social.dal.mysql.SocialClientMapper;
import cn.iocoder.yudao.module.infrastructure.social.service.SocialClientServiceImpl;
import com.binarywang.spring.starter.wxjava.miniapp.properties.WxMaProperties;
import com.binarywang.spring.starter.wxjava.mp.properties.WxMpProperties;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import jakarta.annotation.Nonnull;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.redis.RedisTemplateWxRedisOps;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import me.chanjar.weixin.mp.config.impl.WxMpRedisConfigImpl;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import java.time.Duration;
import java.util.Objects;

/**
 * <pre>
 * OOoO0OOoO0OOOooo0oOOOO0OOOOO0oooOO0ooOOO0Ooooo0OOOOo0ooooO0OOooo0Ooooo0OOOOO
 *  这里是文件说明
 * OOoO0OOoO0OOOooo0oOOOO0OOOOO0oooOO0ooOOO0Ooooo0OOOOo0ooooO0OOooo0Ooooo0OOOOO
 * </pre>
 *
 * @author 山野羡民（1032694760@qq.com）
 * @since 2025/03/07
 * @see SocialClientServiceImpl
 */
@Slf4j
@Service
@Validated
public class WechatClientServiceImpl implements WechatClientService {
    @Resource
    private WxMpService wxMpService;
    @Resource
    private WxMpProperties wxMpProperties;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    private final LoadingCache<String, WxMpService> wxMpServiceCache = CacheUtils.buildAsyncReloadingCache(
            Duration.ofSeconds(10L),
            new CacheLoader<>() {
                @Nonnull
                public WxMpService load(@Nonnull String key) {
                    String[] clientTicket = key.split(":");
                    return WechatClientServiceImpl.this.buildWxMpService(clientTicket[0], clientTicket[1]);
                }
            });
    @Resource
    private WxMaService wxMaService;
    @Resource
    private WxMaProperties wxMaProperties;
    private final LoadingCache<String, WxMaService> wxMaServiceCache = CacheUtils.buildAsyncReloadingCache(
            Duration.ofSeconds(10L),
            new CacheLoader<>() {
                @Nonnull
                public WxMaService load(@Nonnull String key) {
                    String[] clientTicket = key.split(":");
                    return WechatClientServiceImpl.this.buildWxMaService(clientTicket[0], clientTicket[1]);
                }
            });
    @Resource
    private SocialClientMapper socialClientMapper;

    @Override
    public WxMpService buildWxMpService(String clientId, String clientSecret) {
        WxMpRedisConfigImpl var3 = new WxMpRedisConfigImpl(new RedisTemplateWxRedisOps(this.stringRedisTemplate), this.wxMpProperties.getConfigStorage().getKeyPrefix());
        var3.setAppId(clientId);
        var3.setSecret(clientSecret);
        WxMpServiceImpl var4 = new WxMpServiceImpl();
        var4.setWxMpConfigStorage(var3);
        return var4;
    }

    @Override
    public WxMaService buildWxMaService(String clientId, String clientSecret) {
        WxMaRedisBetterConfigImpl var3 = new WxMaRedisBetterConfigImpl(new RedisTemplateWxRedisOps(this.stringRedisTemplate), this.wxMaProperties.getConfigStorage().getKeyPrefix());
        var3.setAppid(clientId);
        var3.setSecret(clientSecret);
        WxMaServiceImpl var4 = new WxMaServiceImpl();
        var4.setWxMaConfig(var3);
        return var4;
    }

    @Override
    public WxMpService getWxMpService(UserTypeEnum userType) {
        SocialClientDO socialClientDO = this.socialClientMapper.selectBySocialTypeAndUserType(SocialTypeEnum.WECHAT_MP.getType(), userType.getValue());
        if (socialClientDO != null && Objects.equals(socialClientDO.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {
            return this.wxMpServiceCache.getUnchecked(socialClientDO.getClientId() + ":" + socialClientDO.getClientSecret());
        } else {
            return this.wxMpService;
        }
    }

    @Override
    public WxMaService getWxMaService(UserTypeEnum userType) {
        SocialClientDO socialClientDO = this.socialClientMapper.selectBySocialTypeAndUserType(SocialTypeEnum.WECHAT_MINI_PROGRAM.getType(), userType.getValue());
        if (socialClientDO != null && Objects.equals(socialClientDO.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {
            return this.wxMaServiceCache.getUnchecked(socialClientDO.getClientId() + ":" + socialClientDO.getClientSecret());
        } else {
            return this.wxMaService;
        }
    }

}
